#include "RangeWindow.h"

#define MOAtoMIL(moa) (moa/3.438)
#define MILtoMOA(mil) (mil*3.438)

RangeWindow::RangeWindow(int w, int h, GBCSolution* inSLN):Fl_Window(w,h,inSLN->Name()){
	begin();
	menu = new Fl_Menu_Bar(0,0,w,30,"MENU");
	Sln=inSLN;
	
	Fl_Menu_Item items[]= {
	    {"&File",0,0,0,FL_SUBMENU},
		  {"Export Data",0,0,0,FL_SUBMENU},
		    {"Comma delimited (.csv)",0,(Fl_Callback*)cb_ExportCSV,this,0},
			{"Excel Spreadsheet (.xls)",0,(Fl_Callback*)cb_ExportExcel,this,0},
			{"OpenOffice Spreadsheet (.ods)",0,(Fl_Callback*)cb_ExportOO,this,0},
			{"HTML Table (.html)",0,(Fl_Callback*)cb_ExportHTML,this,0},
			{"SQL Insert Statement (.sql)",0,(Fl_Callback*)cb_ExportSQL,this,0},
			{"XML File (.xml)",0,(Fl_Callback*)cb_ExportXML,this,0},
			{"PDF Document (.pdf)",0,(Fl_Callback*)cb_ExportPDF,this,0},
			{0},
		  {"&Close",0,(Fl_Callback*)cb_Close,this,0},
		  {0},			
		{"&Minimum Range",0,0,0,FL_SUBMENU},
		  {"0",0,(Fl_Callback*)cb_Min0,this,FL_MENU_RADIO|FL_MENU_VALUE},
		  {"50",0,(Fl_Callback*)cb_Min50,this,FL_MENU_RADIO},
		  {"100",0,(Fl_Callback*)cb_Min100,this,FL_MENU_RADIO},
		  {"250",0,(Fl_Callback*)cb_Min250,this,FL_MENU_RADIO},
		  {"500",0,(Fl_Callback*)cb_Min500,this,FL_MENU_RADIO},
		  {"750",0,(Fl_Callback*)cb_Min750,this,FL_MENU_RADIO},
		  {"1000",0,(Fl_Callback*)cb_Min1000,this,FL_MENU_RADIO},
		  {"2000",0,(Fl_Callback*)cb_Min2000,this,FL_MENU_RADIO},
		  {0},
		{"&Maximum Range",0,0,0,FL_SUBMENU},
		  {"100",0,(Fl_Callback*)cb_Max100,this,FL_MENU_RADIO},
		  {"250",0,(Fl_Callback*)cb_Max250,this,FL_MENU_RADIO},
		  {"500",0,(Fl_Callback*)cb_Max500,this,FL_MENU_RADIO},
		  {"750",0,(Fl_Callback*)cb_Max750,this,FL_MENU_RADIO},
		  {"1000",0,(Fl_Callback*)cb_Max1000,this,FL_MENU_RADIO|FL_MENU_VALUE},
		  {"1760",0,(Fl_Callback*)cb_Max1760,this,FL_MENU_RADIO},
		  {"2000",0,(Fl_Callback*)cb_Max2000,this,FL_MENU_RADIO},
		  {"MAX",0,(Fl_Callback*)cb_MaxMax,this,FL_MENU_RADIO},
		  {0},
		{"&Step Size",0,0,0,FL_SUBMENU},
		  {"1",0,(Fl_Callback*)cb_Step1,this,FL_MENU_RADIO},
		  {"5",0,(Fl_Callback*)cb_Step5,this,FL_MENU_RADIO},
		  {"10",0,(Fl_Callback*)cb_Step10,this,FL_MENU_RADIO|FL_MENU_VALUE},
		  {"25",0,(Fl_Callback*)cb_Step25,this,FL_MENU_RADIO},
		  {"50",0,(Fl_Callback*)cb_Step50,this,FL_MENU_RADIO},
		  {"100",0,(Fl_Callback*)cb_Step100,this,FL_MENU_RADIO},
		  {"250",0,(Fl_Callback*)cb_Step250,this,FL_MENU_RADIO},
		  {0},		  
		{0}
	};
	
	menu->copy(items);
		  
	tbl = new Fl_Browser(5,35,w-10,h-40,"Hello");	

	
	colwidths = (int*)malloc(13*sizeof(int));
	colwidths[0]=70; // Range (yds)
	colwidths[1]=70; // Drop (in)
	colwidths[2]=70; // Drop (MOA)
	colwidths[3]=70; // Drop (MIL)
	colwidths[4]=70; // Target Size (MILs)
	colwidths[5]=70; // Vel (ft/s)
	colwidths[6]=70; // Energy (ft-lb)
	colwidths[7]=70; // Winddrift (in)
	colwidths[8]=70; // Windage (ft)
	colwidths[9]=70; // Windage (MIL)
	colwidths[10]=70; // Time (s)
	colwidths[11]=70; // Drop (13mm clicks)
	colwidths[12]=70; // Drop (17mm clicks)
	colwidths[13]=0;	
	
	tbl->column_widths(colwidths);
	tbl->column_char('\t');
	
	min=0;
	max=1000;
	step=10;
	targetsize=4.0; // inches
	
	GenTable();
		
	end();
	show();
	
}

RangeWindow::~RangeWindow(){
	delete tbl;
	delete menu;
	free(colwidths);


}



/*
   Mini-HOWTO: modifying the range table.
   
   For the table data:
           - update COLUMNS define, headers0, headers1, format, 
             sqlnames and xmlnames arrays below.
           - add a case to GetData for the column data
   For the load data at the top:
           - modify GetPreface() and GetPrefaceLines()

   Note: entries with a blank sqlname are not written to the sql output.
         entries with a blank xmlname are not written to the xml output.
*/

#define COLUMNS 13
static const char *headers0[COLUMNS]={"Range",  "Drop",    "Drop",     "Drop",    "4\" Obj", "Velocity","Energy",  "Wind Drift","Windage",    "Windage",    "Time", "N750",  "N960"};
static const char *headers1[COLUMNS]={"(yards)","(inches)","(MOA)",    "(MIL)",   "(MIL)",   "(ft/s)",  "(ft-lbs)","(inches)",  "(MOA)",      "(MIL)",      "(s)",  "Clicks","Clicks"};
static const char *format  [COLUMNS]={"%.0f",   "%.2f",    "%.2f",     "%.2f",    "%.2f",    "%.0f",    "%.0f",    "%.2f",      "%.2f",       "%.2f",       "%.3f", "%2.0f", "%2.0f"};
static const char *sqlnames[COLUMNS]={"range",  "drop",    "elev_moa", "elev_mil","",        "velocity","energy",  "winddrift", "windage_moa","windage_mil","time", "clicks13mm","clicks17mm"};
static const char *xmlnames[COLUMNS]={"Range",  "Drop",    "ElevMOA",  "ElevMIL", "",        "Velocity","Energy",  "WindDrift", "WindageMOA", "WindageMIL", "Time", "clicks13mm","clicks17mm"};

int RangeWindow::GetColumns(void){
  return COLUMNS;
}

int RangeWindow::GetHeaderLines(void){
  return 2;
}


int RangeWindow::GetPrefaceLines(void){
  return 5;
}

void RangeWindow::GetPreface(int l, char *str){
    switch (l) {
          case 0: sprintf(str,"Ballistic Coefficient: %.3f   Projectile Weight: %d grains",Sln->BC(), Sln->Weight());
                  break;
          case 1: sprintf(str,"Initial Velocity: %d (ft/s)   Zero Range: %d yards  (%d metres) Shooting Angle: %d degrees",Sln->MuzzleVelocity(), Sln->ZeroRange(), (int)(Sln->ZeroRange()*0.9144), Sln->ShootingAngle());
                  break;
          case 2: sprintf(str,"Wind Velocity:  %d mph (%1.1f m/sec)   Wind Direction: %d degrees",Sln->WindSpeed(), Sln->WindSpeed()*0.44704, Sln->WindAngle());
                  break;
          case 3: sprintf(str,"Altitude: %d feet (%1.0f M)  Barometer: %.2f in-Hg (%1.0f mbar)",
	                  Sln->Altitude(), Sln->Altitude() * 0.3048,
	                  Sln->Pressure(), Sln->Pressure() * 33.8639);
	          break;
          case 4: sprintf(str,"Temperature: %d F (%1.0f C)  Relative Humidity: %d%%",
	          Sln->Temp(), 100.0/(212-32) * (Sln->Temp() - 32),
	          Sln->Humidity());
	          break;
         default: *str='\0';
                  break;
    }
}

const char *RangeWindow::GetHeader(int col, int row){
  if (col<0 || col>=GetColumns()) return NULL;
  if (row==0) return headers0[col];
  if (row==1) return headers1[col];
  return NULL;
}


#define digisight_unit(mm) (25.4/(mm*0.9144))

/* returns the data for a column at a given range */
int RangeWindow::GetData(int col, int range, char *buf){
  if (col>=GetColumns()) { *buf='\0'; return 0; }
  if (range<0)           { *buf='\0'; return 0; }
  
  if (range==0 && 
      (col==2 || col==3 || col==4 || col==8 || col==9 || col==11 || col==12)
     ) return sprintf(buf, "-");
  
  double v=0;
  switch (col) {
      case 0: v= Sln->GetRange(range);				break;
      case 1: v= Sln->GetPath(range);				break;
      case 2: v= Sln->GetMOA(range);				break;
      case 3: v= MOAtoMIL(Sln->GetMOA(range));			break;
      case 4: v= (targetsize / 36.0 * 1000) / range;		break;
      case 5: v= Sln->GetVelocity(range);			break;
      case 6: v= Sln->GetVelocity(range);
              v= Sln->Weight()*v*v/450436;
              break;
      case 7: v= Sln->GetWindage(range);			break;
      case 8: v= Sln->GetWindageMOA(range);			break;
      case 9: v= MOAtoMIL(Sln->GetWindageMOA(range));		break;
      case 10:v= Sln->GetTime(range);				break;
      case 11:v= -Sln->GetMOA(range) * digisight_unit(13);	break;
      case 12:v= -Sln->GetMOA(range) * digisight_unit(17);	break;
      }
      
  return sprintf(buf, format[col], v);
}

static char buffer[20];
char *RangeWindow::GetData(int col, int range){
  GetData(col, range, buffer);
  return buffer;
}


void RangeWindow::GenTable(){
	
	
	tbl->clear();
	
	int MIN=this->min;
	int MAX=this->max;
	int STEP=this->step;
	
	int num=Sln->MaxRows();

	// printf("NUM: %d",num);

	if (MAX>num) MAX=num;
	if (MIN>MAX) MIN=MAX;
	
	char* str = (char*)malloc(1024*sizeof(char));
	char* strp;
	
	// Print some general information about the load.
	sprintf(str, "@b%s", Sln->Name());
	tbl->add(str);

        for (int n=0; n < GetPrefaceLines(); n++) {
            GetPreface(n, str);
            tbl->add(str);
        }
	
	tbl->add("");
	
	
	// headers
	for (int hline=0; hline < GetHeaderLines(); hline++) {
	    int col;
	    strp=str;
            for (col=0; col < GetColumns()-1; col++) {
                strp+=sprintf(strp, "@b@c%s\t", GetHeader(col, hline));
                }
            sprintf(strp, "@b@c%s", GetHeader(col,hline));
            tbl->add(str);
        }
            
        // actual data
	for (int n=MIN;n<=MAX;n=n+STEP){
	    int col;
	    strp=str;
	    for (col=0; col < GetColumns()-1; col++) {
	        strp+=sprintf(strp, "@c%s\t", GetData(col, n));
	        }
            sprintf(strp, "@c%s", GetData(col,n));
            tbl->add(str,0);
	}
	
	free(str);
}




void RangeWindow::cb_Nothing(Fl_Widget* t, void* v){
	//exit(0);
}


void RangeWindow::cb_Min0(Fl_Widget* t, void* v){
	RangeWindow* T=(RangeWindow*)v;
	T->min=0;
	T->GenTable();
}
void RangeWindow::cb_Min50(Fl_Widget* t, void* v){
	RangeWindow* T=(RangeWindow*)v;
	T->min=50;
	T->GenTable();
}
void RangeWindow::cb_Min100(Fl_Widget* t, void* v){
	RangeWindow* T=(RangeWindow*)v;
	T->min=100;
	T->GenTable();
}
void RangeWindow::cb_Min250(Fl_Widget* t, void* v){
	RangeWindow* T=(RangeWindow*)v;
	T->min=250;
	T->GenTable();
}
void RangeWindow::cb_Min500(Fl_Widget* t, void* v){
	RangeWindow* T=(RangeWindow*)v;
	T->min=500;
	T->GenTable();
}
void RangeWindow::cb_Min750(Fl_Widget* t, void* v){
	RangeWindow* T=(RangeWindow*)v;
	T->min=750;
	T->GenTable();
}
void RangeWindow::cb_Min1000(Fl_Widget* t, void* v){
	RangeWindow* T=(RangeWindow*)v;
	T->min=1000;
	T->GenTable();
}
void RangeWindow::cb_Min2000(Fl_Widget* t, void* v){
	RangeWindow* T=(RangeWindow*)v;
	T->min=2000;
	T->GenTable();
}


void RangeWindow::cb_Max100(Fl_Widget* t, void* v){
	RangeWindow* T=(RangeWindow*)v;
	T->max=100;
	T->GenTable();
}
void RangeWindow::cb_Max250(Fl_Widget* t, void* v){
	RangeWindow* T=(RangeWindow*)v;
	T->max=250;
	T->GenTable();
}
void RangeWindow::cb_Max500(Fl_Widget* t, void* v){
	RangeWindow* T=(RangeWindow*)v;
	T->max=500;
	T->GenTable();
}
void RangeWindow::cb_Max750(Fl_Widget* t, void* v){
	RangeWindow* T=(RangeWindow*)v;
	T->max=750;
	T->GenTable();
}
void RangeWindow::cb_Max1000(Fl_Widget* t, void* v){
	RangeWindow* T=(RangeWindow*)v;
	T->max=1000;
	T->GenTable();
}
void RangeWindow::cb_Max1760(Fl_Widget* t, void* v){
	RangeWindow* T=(RangeWindow*)v;
	T->max=1760;
	T->GenTable();
}
void RangeWindow::cb_Max2000(Fl_Widget* t, void* v){
	RangeWindow* T=(RangeWindow*)v;
	T->max=2000;
	T->GenTable();
}
void RangeWindow::cb_MaxMax(Fl_Widget* t, void* v){
	RangeWindow* T=(RangeWindow*)v;
	int mr = T->Sln->MaxRows();
	T->max=mr;
	T->GenTable();
}


void RangeWindow::cb_Step1(Fl_Widget* t, void* v){
	RangeWindow* T=(RangeWindow*)v;
	T->step=1;
	T->GenTable();
}
void RangeWindow::cb_Step5(Fl_Widget* t, void* v){
	RangeWindow* T=(RangeWindow*)v;
	T->step=5;
	T->GenTable();
}
void RangeWindow::cb_Step10(Fl_Widget* t, void* v){
	RangeWindow* T=(RangeWindow*)v;
	T->step=10;
	T->GenTable();
}
void RangeWindow::cb_Step25(Fl_Widget* t, void* v){
	RangeWindow* T=(RangeWindow*)v;
	T->step=25;
	T->GenTable();
}
void RangeWindow::cb_Step50(Fl_Widget* t, void* v){
	RangeWindow* T=(RangeWindow*)v;
	T->step=50;
	T->GenTable();
}
void RangeWindow::cb_Step100(Fl_Widget* t, void* v){
	RangeWindow* T=(RangeWindow*)v;
	T->step=100;
	T->GenTable();
}
void RangeWindow::cb_Step250(Fl_Widget* t, void* v){
	RangeWindow* T=(RangeWindow*)v;
	T->step=250;
	T->GenTable();
}


void RangeWindow::cb_ExportCSV(Fl_Widget* f, void* vtt){

	RangeWindow* T = (RangeWindow*)vtt;
	
	char* fname=NULL;
	fname = fl_file_chooser("Please select a location and filename to export the CSV data.","*.csv","OutputData.csv",0);
	if (fname==NULL) return;

	
	FILE* ofile = fopen(fname,"w");
	
	// Print the output to a file.
	
	int MIN=T->min;
	int MAX=T->max;
	int STEP=T->step;

	// headers
	for (int hline=0; hline < T->GetHeaderLines(); hline++) {
	    int col;
            for (col=0; col < T->GetColumns()-1; col++) {
                fprintf(ofile, "%s,", T->GetHeader(col,hline));
            }
            fprintf(ofile,"%s\n", T->GetHeader(col,hline));
        }
	
	int num=T->Sln->MaxRows();
	if (MAX>num) MAX=num;
	if (MIN>MAX) MIN=MAX;
	
	// actual data
	for (int n=MIN;n<=MAX;n=n+STEP){
		int col;
		for (col=0; col < T->GetColumns()-1; col++) {
		    fprintf(ofile, "%s,", T->GetData(col, n));
                }
                fprintf(ofile,"%s\n", T->GetData(col, n));
	}
	
	fclose(ofile);
	
 
}
void RangeWindow::cb_ExportExcel(Fl_Widget* f, void* vtt){

	RangeWindow* T = (RangeWindow*)vtt;
	
	char* fname=NULL;
	fname = fl_file_chooser("Please select a location and filename to export the Excel data.","*.xls","OutputData.xls",0);
	if (fname==NULL) return;

	FILE* ofile = fopen(fname,"w");
	
	// Print the output to a file.
	
	int MIN=T->min;
	int MAX=T->max;
	int STEP=T->step;

	fprintf(ofile, "\n<html><head><title>%s</title></head>", T->Sln->Name());
	fprintf(ofile, "\n\n<table>");

	// headers
	for (int hline=0; hline < T->GetHeaderLines(); hline++) {
	    int col;
	    fprintf(ofile, "<tr>");
            for (col=0; col < T->GetColumns()-1; col++) {
                fprintf(ofile, "<td>%s</td>", T->GetHeader(col,hline));
            }
            fprintf(ofile,"<td>%s</td></tr>\n", T->GetHeader(col,hline));
        }
	
	int num=T->Sln->MaxRows();
	if (MAX>num) MAX=num;
	if (MIN>MAX) MIN=MAX;
		
	for (int n=MIN;n<=MAX;n=n+STEP){
		int col;
		fprintf(ofile, "<tr>");
		for (col=0; col < T->GetColumns()-1; col++) {
		    fprintf(ofile, "<td>%s</td>", T->GetData(col, n));
                }
                fprintf(ofile,"<td>%s</td></tr>\n", T->GetData(col, n));
	}
	
	fprintf(ofile,"\n</table></html>");
	fclose(ofile);
}


void RangeWindow::cb_ExportOO(Fl_Widget* f, void* vtt){

	RangeWindow* T = (RangeWindow*)vtt;
	
	char* fname=NULL;
	
	fname = fl_file_chooser("Please select a location and filename to export the OpenOffice spreadsheet.","*.ods","OutputData.ods",0);
	if (fname==NULL) return;

	FILE* ofile = fopen(fname,"w");
	
	// Print the output to a file.
	int MIN=T->min;
	int MAX=T->max;
	int STEP=T->step;

	fprintf(ofile, "\n<html><head><title>%s</title></head>", T->Sln->Name());
	fprintf(ofile, "\n\n<table>");

	// headers
	for (int hline=0; hline < T->GetHeaderLines(); hline++) {
	    int col;
	    fprintf(ofile, "<tr>");
            for (col=0; col < T->GetColumns()-1; col++) {
                fprintf(ofile, "<td>%s</td>", T->GetHeader(col,hline));
            }
            fprintf(ofile,"<td>%s</td></tr>\n", T->GetHeader(col,hline));
        }

	int num=T->Sln->MaxRows();
	if (MAX>num) MAX=num;
	if (MIN>MAX) MIN=MAX;
	

	for (int n=MIN;n<=MAX;n=n+STEP){
		int col;
		fprintf(ofile, "<tr>");
		for (col=0; col < T->GetColumns()-1; col++) {
		    fprintf(ofile, "<td>%s</td>", T->GetData(col, n));
                }
                fprintf(ofile,"<td>%s</td></tr>\n", T->GetData(col, n));
	}
	
	fprintf(ofile,"\n</table></html>");
	fclose(ofile);
}



void RangeWindow::cb_ExportHTML(Fl_Widget* f , void* vtt){
	RangeWindow* T = (RangeWindow*)vtt;
	
	char* fname=NULL;
	fname = fl_file_chooser("Please select a location and filename to export the HTML data.","*.html","OutputData.html",0);
	if (fname==NULL) return;

	FILE* ofile = fopen(fname,"w");
	
	// Print the output to a file.
	
	int MIN=T->min;
	int MAX=T->max;
	int STEP=T->step;

	
	fprintf(ofile, "\n<html><head><title>%s</title></head>",T->Sln->Name());
	fprintf(ofile, "\n\n<table width=560 bgcolor=black>");
	
	// headers
	for (int hline=0; hline < T->GetHeaderLines(); hline++) {
	    int col;
	    fprintf(ofile, "<tr>\n");
            for (col=0; col < T->GetColumns()-1; col++) {
                fprintf(ofile, "\t<td width=70 bgcolor=white align=center><b>%s</b></td>", T->GetHeader(col,hline));
            }
            fprintf(ofile,"\t<td width=70 bgcolor=white align=center>%s</b></td>\n</tr>\n", T->GetHeader(col,hline));
        }
	
	int num=T->Sln->MaxRows();
	if (MAX>num) MAX=num;
	if (MIN>MAX) MIN=MAX;
	
	for (int n=MIN;n<=MAX;n=n+STEP){
		int col;
		fprintf(ofile, "<tr>");
		for (col=0; col < T->GetColumns()-1; col++) {
		    fprintf(ofile, "\t<td width=70 bgcolor=white align=center>%s</td>", T->GetData(col, n));
                }
                fprintf(ofile,"\t<td width=70 bgcolor=white align=center>%s</td>\n</tr>\n", T->GetData(col, n));
	}
	
	fprintf(ofile,"\n</table></html>");
	fclose(ofile);
}

void RangeWindow::cb_ExportSQL(Fl_Widget* f, void* vtt){

	RangeWindow* T = (RangeWindow*)vtt;
	
	char* fname=NULL;
	fname = fl_file_chooser("Please select a location and filename to export the SQL File.","*.sql","OutputData.sql",0);
	if (fname==NULL) return;

	FILE* ofile = fopen(fname,"w");
	
	// Print the output to a file.
	
	int MIN=T->min;
	int MAX=T->max;
	int STEP=T->step;

	int num=T->Sln->MaxRows();
	if (MAX>num) MAX=num;
	if (MIN>MAX) MIN=MAX;

	char* str = (char*)malloc(1024*sizeof(char));
	char* strp;

        // The column names are in their own array. Columns with blank sql names are
        // not written to the output.	
	for (int hline=0; hline < T->GetHeaderLines(); hline++) {
	    int col;
	    strp=str;
            for (col=0; col < T->GetColumns()-1; col++) {
                if (sqlnames[col] && *sqlnames[col])
                   strp+=sprintf(strp, "%s,", sqlnames[col]);
            }
            sprintf(strp, "%s", sqlnames[col]);
        }

	for (int n=MIN;n<=MAX;n=n+STEP){
		int col;
		fprintf(ofile, "INSERT INTO BallisticData (%s) VALUES (", str);
		for (col=0; col < T->GetColumns()-1; col++) {
		    if (sqlnames[col] && *sqlnames[col])
		       fprintf(ofile, "%s,", T->GetData(col, n));
                }
                fprintf(ofile,"%s);\n", T->GetData(col, n));
	}
	
	free(str);
	fclose(ofile);
}

void RangeWindow::cb_ExportXML(Fl_Widget* f, void* vtt){


	RangeWindow* T = (RangeWindow*)vtt;
	
	char* fname=NULL;
	fname = fl_file_chooser("Please select a location and filename to export the XML File.","*.xml","OutputData.xml",0);
	if (fname==NULL) return;

	FILE* ofile = fopen(fname,"w");
	
	// Print the output to a file.
	
	int MIN=T->min;
	int MAX=T->max;
	int STEP=T->step;

	fprintf(ofile, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
	

	fprintf(ofile, "\n<SolutionTitle>%s</SolutionTitle>",T->Sln->Name());
	fprintf(ofile, "\n\n<SolutionData>");
					
	int num=T->Sln->MaxRows();
	if (MAX>num) MAX=num;
	if (MIN>MAX) MIN=MAX;

	for (int n=MIN;n<=MAX;n=n+STEP){
		fprintf(ofile,"\n<SolutionElement>\n");
		int col;
		for (col=0; col < T->GetColumns(); col++) {
		    if (xmlnames[col] && *xmlnames[col])
		       fprintf(ofile, "\t<%s>%s</%s>\n", xmlnames[col], T->GetData(col, n), xmlnames[col]);
                }
		fprintf(ofile,"</SolutionElement>\n");
	}
	
	fprintf(ofile,"\n</SolutionData>");
	
	
	fclose(ofile);
}


void RangeWindow::cb_Close(Fl_Widget* f, void* v){
	RangeWindow* T = (RangeWindow*)v;
	T->~RangeWindow();
}

	

void RangeWindow::cb_ExportPDF(Fl_Widget*, void* vtt){

	RangeWindow* T = (RangeWindow*)vtt;
	
	char* fname=NULL;
	fname = fl_file_chooser("Please select a location and filename to save the PDF Document.","*.pdf","OutputData.pdf",0);
	if (fname==NULL) return;


    const char *page_title = T->Sln->Name();
    HPDF_Doc  pdf;
    HPDF_Page page;
    HPDF_Font def_font;
    HPDF_REAL tw;
    HPDF_REAL height;
    HPDF_REAL width;
    pdf = HPDF_New (NULL, NULL);

    /* Add a new page object. */
    page = HPDF_AddPage (pdf);
    height = HPDF_Page_GetHeight (page);
    width = HPDF_Page_GetWidth (page);
	
    /* Print the title of the page (with positioning center). */
    def_font = HPDF_GetFont (pdf, "Helvetica", NULL);
    HPDF_Page_SetFontAndSize (page, def_font, 16);
    tw = HPDF_Page_TextWidth (page, page_title);
    HPDF_Page_BeginText (page);
    HPDF_Page_TextOut (page, (width - tw) / 2, height - 50, page_title);
    HPDF_Page_EndText (page);
	
	HPDF_Page_SetFontAndSize(page,def_font,8);
	tw = HPDF_Page_TextWidth(page,"GNU Exterior Ballistics, v1.05");
	HPDF_Page_BeginText(page);
	HPDF_Page_TextOut (page, (width-tw)/2, height-62, "GNU Exterior Ballistics, v1.05");
	HPDF_Page_EndText(page);
	

    /* output Row Data. */
	int margin=50;
	int colsize=45;
	int rowheight=10;
	int footer=50;
	int row=0;
		
	HPDF_Page_SetFontAndSize (page, def_font, 10);
    HPDF_Page_BeginText (page);
	
	// First print the weather condition data and such.
	char* str = (char*)malloc(1024*sizeof(char));
	// Print some general information about the load.
        for (int n=0; n < T->GetPrefaceLines(); n++) {
            T->GetPreface(n, str);
	    HPDF_Page_TextOut (page,margin+0*colsize, height - 80 - rowheight*row, str);
	    row++;
        }
	row++;
	
	// headers
	for (int hline=0; hline < T->GetHeaderLines(); hline++) {
	    int col;
            for (col=0; col < T->GetColumns(); col++) {
                HPDF_Page_TextOut(page,margin+col*colsize, height-80-rowheight*row, T->GetHeader(col,hline));
            }
            row++;
        }
        row++;
            
    HPDF_Page_EndText (page);



	// Print the rows iteratively
	int MIN=T->min;
	int MAX=T->max;
	int STEP=T->step;
	HPDF_Page_SetFontAndSize (page, def_font, 8);
	
	for (int n=MIN;n<=MAX;n=n+STEP){
		// Print the row.
		HPDF_Page_BeginText (page);
		for (int col=0; col < T->GetColumns(); col++) {
		    HPDF_Page_TextOut(page,margin+col*colsize, height - 80 - rowheight*row, T->GetData(col, n));
                }
		HPDF_Page_EndText (page);
		row++;
		
		if ((height-80-rowheight*row)<footer){
		
			// Insert a new page, we have come to the end of this one.
			page = HPDF_AddPage (pdf);
			HPDF_Page_SetFontAndSize (page, def_font, 10);
			HPDF_Page_BeginText (page);
                	// headers
                	row=0;
                	for (int hline=0; hline < T->GetHeaderLines(); hline++) {
                	    int col;
                            for (col=0; col < T->GetColumns(); col++) {
                                HPDF_Page_TextOut(page,margin+col*colsize, height-80-rowheight*row, T->GetHeader(col,hline));
                            }
                            row++;
                        }
			HPDF_Page_EndText (page);

			HPDF_Page_SetFontAndSize (page, def_font, 8);
			row++;
		}
	

	}

	free(str);
	
    HPDF_SaveToFile (pdf, fname);



    /* clean up */
    HPDF_Free (pdf);


}
